var E_WINNER        = 1000000000;
var E_WINNER_NEXT   = 10000000;
var E_GOOD          = 100000;
var E_NORMAL        = 1000;
var E_BEGIN         = 10;
var E_NOTHING       = 1;


function Estimate() {
    this.game = null;
    this.lastMove = []; 
}

Estimate.prototype.addMove = function(xx,yy, valueXY) {
    this.lastMove.push({x: xx, y: yy, val: valueXY});
    // 7 poniewaz 5 + 2, 1 z przodu i 1 z tylu
    if (this.lastMove.length > 7) {
        this.lastMove.shift();
    }
};

Estimate.prototype.clearMove = function() {
    this.lastMove = [];
};

Estimate.prototype.calcPoints = function(value) {
    /**
    * jak w pieciu komorkach tablicy lastMoves 
    * jest jakis znak o wartosci value
    * a reszta znakow to wartosc 0
    * to zacznij punktowac
    * 100 = 5 x value
    * 80 = 4 x value
    * 50 = 3 x value
    * 30 = 2 x value
    * 10 = 1 x value
    */
    // pkt 1, czy sa tylko znaki value i znak 0

    var points = 0;
    var qty = this.lastMove.length;
    
    if (qty >= 5) {

       /**
        * utworzenie tablic do analizy
        */
       var moves = [];
       if (qty >= 5) {
           moves.push(this.lastMove.slice(0,5));
       }
       if (qty >= 6) {
           var tmp = this.lastMove.slice(1,6);
           tmp.push(this.lastMove[0]);
           moves.push(tmp);
       }
       if (qty >= 7) {
           var tmp = this.lastMove.slice(1, 6);
           tmp.push(this.lastMove[0]);
           tmp.push(this.lastMove[6]);
           moves.push(tmp);

           tmp = this.lastMove.slice(2,7);
           tmp.push(this.lastMove[1]);
           moves.push(tmp);
       }

       for (var ii in moves) {
           var move = moves[ii];
           var calcAll = 0;
           var calcNextTo = 0;



           for (var i = 0; i < 5; i++) {
               var val = move[i].val;
               if (val == 0 || val == value) {
                   if (val == value) {
                       calcAll++;
                       calcNextTo++;
                   } else {
                       // jezeli nastepny ruch istnieje i nie jest ona wartoscia pusta [0 - zero]
                       if (typeof move[i + 1] !== 'undefined' && move[i + 1].val != 0) {
                           calcNextTo = 0;
                       }
                   }
               } else {
                   calcAll = 0;
                   calcNextTo = 0;
                   break;
               }
           }

           /**
            * zlozenia
            * 3 razy w 5 polach
            * 
            */
           if (calcAll == 5) {
               points += E_WINNER;
           }

           if (calcAll == 4) {
               
               /**
                * wazne !! z powodu tych warunkow plansza do gry musi miec
                * minimum 6 x 6 !!!
                */
               if (move[0].val == 0 && typeof move[6] !== 'undefined' && move[6].val == 0) {
                   // uwaga sytuacja niebezpieczna
                   points += E_WINNER_NEXT;
               } else if (move[4].val == 0 && typeof move[5] !== 'undefined' && move[5].val == 0) {
                   // uwaga sytuacja niebezpieczna
                   points += E_WINNER_NEXT;
               } else {
                    points += E_GOOD * 2;
               }
           }

           if (calcAll == 3) {
               
               if (calcNextTo == 3) {
                   if ( move[0].val == 0 || move[1].val == 0 || (typeof move[5] !== 'undefined' && move[5].val == 0) ||
                        move[3].val == 0 || move[4].val == 0 || (typeof move[6] !== 'undefined' && move[6].val == 0))
                   {
                       points += E_GOOD;
                   }  else {
                       points += E_GOOD / 2;
                   }
               } else {
                   points += E_BEGIN;
               }
           }

           if (calcAll == 2) {
               points += E_BEGIN;
           }

           if (calcAll == 1) {
               points += E_NOTHING;
           }
       }
    }

    return points;
};


Estimate.prototype.getEstimateForValue = function(v) {
    
    var points = 0;
    var size = this.game.getSize();


    /**
     * vertical
     */
    for (var x = 0; x < size; x++) {

        this.clearMove();

        for (var y = 0; y < size; y++) {
            var value = this.game.getValue(x, y);
            this.addMove(x, y, value);
            points += this.calcPoints(v);
        }
    }

    /**
     * horyzontal
     */
    for (var y = 0; y < size; y++) {

        this.clearMove();

        for (var x = 0; x < size; x++) {
            var value = this.game.getValue(x, y);
            this.addMove(x, y, value);
            points += this.calcPoints(v);
        }
    }

    /**
     * left to right cross JEST JUZ OK
     */
    for (var x = 0; x < size; x++) {

        this.clearMove();

        // petla LR_1
        // analizuje srodkowa przekatna
        for (var y = 0; y < size; y++) {

            var xx = y + x;

            var value = this.game.getValue(xx, y);
            if (value === null) {
                this.clearMove();
                continue;
            }
            this.addMove(xx, y, value);
            points += this.calcPoints(v);
        }

        this.clearMove();

        // petla LR_2
        for (var y = 0; y < size; y++) {

            // warunek zeby dwa razy nie analizowac srodkowej przekatnej
            // ta srodkowa przekatna jest analizowana przez petle LR_1
            if (x == 0) {
                this.clearMove();
                continue;
            }

            var xx = y - x;

            var value = this.game.getValue(xx, y);
            if (value === null) {
                this.clearMove();
                continue;
            }
            this.addMove(xx, y, value);
            points += this.calcPoints(v);
        }
    }

    /**
     * right to left cross JEST JUZ OK
     */
    for (var x = size - 1; x >= 0; x--) {

        this.clearMove();

        // petla RL_1
        // analizuje srodkowa przekatna
        for (var y = 0; y < size; y++) {

            var xx = x - y;

            var value = this.game.getValue(xx, y);
            if (value === null) {
                this.clearMove();
                continue;
            }
            this.addMove(xx, y, value);
            points += this.calcPoints(v);
        }

        this.clearMove();

        // petla RL_2
        for (var y = 0; y < size; y++) {

            // warunek zeby dwa razy nie analizowac srodkowej przekatnej
            // ta srodkowa przekatna jest analizowana przez petle RL_1
            if (x == size - 1) {
                this.clearMove();
                continue;
            }

            // metoda prob i bledow
            var xx = x - y + 2 * (size - 1 - x);

            var value = this.game.getValue(xx, y);
            if (value === null) {
                this.clearMove();
                continue;
            }
            this.addMove(xx, y, value);
            points += this.calcPoints(v);
        }
    }

    return points;

};
